﻿using System;
using System.Collections.Generic;
using System.Text;
using System.IO;
using System.Security.Cryptography;

namespace GTTSOfLibrary.EncryptClasses
{
    /// <summary>
    /// 此处定义的是DES加密,为了便于今后的管理和维护
    /// 请不要随便改动密码,或者改变了密码后请一定要
    /// 牢记先前的密码,否则将会照成不可预料的损失
    /// </summary>
    public class DESEncrypt
    {
        #region "member fields"
        private string iv = "12345678";
        private string key = "12345678";
        private Encoding encoding = new UnicodeEncoding();
        private DES des;
        #endregion
        /// <summary>
        /// 构造函数
        /// </summary>
        public DESEncrypt()
        {
            des = new DESCryptoServiceProvider();
        }
        #region "propertys"
        /// <summary>
        /// 设置加密密钥
        /// </summary>
        public string EncryptKey
        {
            get { return this.key; }
            set
            {
                this.key = value;
            }
        }
        /// <summary>
        /// 要加密字符的编码模式
        /// </summary>
        public Encoding EncodingMode
        {
            get { return this.encoding; }
            set { this.encoding = value; }
        }
        #endregion
        #region "methods"
        /// <summary>
        /// 加密字符串并返回加密后的结果
        /// </summary>
        /// <param name="str"></param>
        /// <returns></returns>
        public string EncryptString(string str)
        {
            byte[] ivb = Encoding.ASCII.GetBytes(this.iv);
            byte[] keyb = Encoding.ASCII.GetBytes(this.EncryptKey);//得到加密密钥
            byte[] toEncrypt = this.EncodingMode.GetBytes(str);//得到要加密的内容
            byte[] encrypted;
            ICryptoTransform encryptor = des.CreateEncryptor(keyb, ivb);
            MemoryStream msEncrypt = new MemoryStream();
            CryptoStream csEncrypt = new CryptoStream(msEncrypt, encryptor, CryptoStreamMode.Write);
            csEncrypt.Write(toEncrypt, 0, toEncrypt.Length);
            csEncrypt.FlushFinalBlock();
            encrypted = msEncrypt.ToArray();
            csEncrypt.Close();
            msEncrypt.Close();
            return this.EncodingMode.GetString(encrypted);
        }
        /// <summary>
        /// 加密指定的文件,如果成功返回True,否则false
        /// </summary>
        /// <param name="filePath">要加密的文件路径</param>
        /// <param name="outPath">加密后的文件输出路径</param>
        public void EncryptFile(string filePath, string outPath)
        {
            bool isExist = File.Exists(filePath);
            if (isExist)//如果存在
            {
                byte[] ivb = Encoding.ASCII.GetBytes(this.iv);
                byte[] keyb = Encoding.ASCII.GetBytes(this.EncryptKey);
                //得到要加密文件的字节流
                FileStream fin = new FileStream(filePath, FileMode.Open, FileAccess.Read);
                StreamReader reader = new StreamReader(fin, this.EncodingMode);
                string dataStr = reader.ReadToEnd();
                byte[] toEncrypt = this.EncodingMode.GetBytes(dataStr);
                fin.Close();
                FileStream fout = new FileStream(outPath, FileMode.Create, FileAccess.Write);
                ICryptoTransform encryptor = des.CreateEncryptor(keyb, ivb);
                CryptoStream csEncrypt = new CryptoStream(fout, encryptor, CryptoStreamMode.Write);
                try
                {
                    //加密得到的文件字节流
                    csEncrypt.Write(toEncrypt, 0, toEncrypt.Length);
                    csEncrypt.FlushFinalBlock();
                }
                catch (Exception err)
                {
                    throw new ApplicationException(err.Message);
                }
                finally
                {
                    try
                    {
                        fout.Close();
                        csEncrypt.Close();
                    }
                    catch
                    {
                        ;
                    }
                }
            }
            else
            {
                throw new FileNotFoundException("没有找到指定的文件");
            }
        }
        /// <summary>
        /// 文件加密函数的重载版本,如果不指定输出路径,
        /// 那么原来的文件将被加密后的文件覆盖
        /// </summary>
        /// <param name="filePath"></param>
        public void EncryptFile(string filePath)
        {
            this.EncryptFile(filePath, filePath);
        }
        /// <summary>
        /// 解密给定的字符串
        /// </summary>
        /// <param name="str">要解密的字符</param>
        /// <returns></returns>
        public string DecryptString(string str)
        {
            byte[] ivb = Encoding.ASCII.GetBytes(this.iv);
            byte[] keyb = Encoding.ASCII.GetBytes(this.EncryptKey);
            byte[] toDecrypt = this.EncodingMode.GetBytes(str);
            byte[] deCrypted = new byte[toDecrypt.Length];
            ICryptoTransform deCryptor = des.CreateDecryptor(keyb, ivb);
            MemoryStream msDecrypt = new MemoryStream(toDecrypt);
            CryptoStream csDecrypt = new CryptoStream(msDecrypt, deCryptor, CryptoStreamMode.Read);
            try
            {
                csDecrypt.Read(deCrypted, 0, deCrypted.Length);
            }
            catch (Exception err)
            {
                throw new ApplicationException(err.Message);
            }
            finally
            {
                try
                {
                    msDecrypt.Close();
                    csDecrypt.Close();
                }
                catch { ;}
            }
            return this.EncodingMode.GetString(deCrypted);
        }
        /// <summary>
        /// 解密指定的文件
        /// </summary>
        /// <param name="filePath">要解密的文件路径</param>
        /// <param name="outPath">解密后的文件输出路径</param>
        public void DecryptFile(string filePath, string outPath)
        {
            bool isExist = File.Exists(filePath);
            if (isExist)//如果存在
            {
                byte[] ivb = Encoding.ASCII.GetBytes(this.iv);
                byte[] keyb = Encoding.ASCII.GetBytes(this.EncryptKey);
                FileInfo file = new FileInfo(filePath);
                byte[] deCrypted = new byte[file.Length];
                //得到要解密文件的字节流
                FileStream fin = new FileStream(filePath, FileMode.Open, FileAccess.Read);
                //解密文件
                try
                {
                    ICryptoTransform decryptor = des.CreateDecryptor(keyb, ivb);
                    CryptoStream csDecrypt = new CryptoStream(fin, decryptor, CryptoStreamMode.Read);
                    csDecrypt.Read(deCrypted, 0, deCrypted.Length);
                }
                catch (Exception err)
                {
                    throw new ApplicationException(err.Message);
                }
                finally
                {
                    try
                    {
                        fin.Close();
                    }
                    catch { ;}
                }
                FileStream fout = new FileStream(outPath, FileMode.Create, FileAccess.Write);
                fout.Write(deCrypted, 0, deCrypted.Length);
                fout.Close();
            }
            else
            {
                throw new FileNotFoundException("指定的解密文件没有找到");
            }
        }
        /// <summary>
        /// 解密文件的重载版本,如果没有给出解密后文件的输出路径,
        /// 则解密后的文件将覆盖先前的文件
        /// </summary>
        /// <param name="filePath"></param>
        public void DecryptFile(string filePath)
        {
            this.DecryptFile(filePath, filePath);
        }
        #endregion
    }
}
